home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / graphicgems4.lha / GemsIV / vec_mat / ray / Scene3D.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-06  |  5.5 KB  |  217 lines

  1. #include "Scene3D.h"
  2. #include "Sphere.h"
  3. #include "Polyhedron.h"
  4.  
  5. #include <string.h>
  6. #include <ctype.h>
  7.  
  8. #define FAR_AWAY 1e06
  9.  
  10. /************************************************************************
  11. *                                    *
  12. * Class constructor                            *
  13. *                                    *
  14. ************************************************************************/
  15.  
  16. Scene3D::Scene3D()
  17. {
  18. #define CAPACITY 128
  19.  
  20. lList = new Light*[CAPACITY];
  21. pList = new Primitive*[CAPACITY];
  22. lightN = primitiveN = 0;
  23. }
  24.  
  25. /************************************************************************
  26. *                                    *
  27. * Class destructor                            *
  28. *                                    *
  29. ************************************************************************/
  30.  
  31. Scene3D::~Scene3D()
  32. {
  33. int i;
  34.  
  35. // delete the light sources
  36. for (i = 0; i < lightN; i++)
  37.     delete lList[i];
  38. delete lList;
  39.  
  40. // delete the primitives
  41. for (i = 0; i < primitiveN; i++)
  42.     delete pList[i];
  43. delete pList;
  44.  
  45. // delete the camera
  46. delete camera;
  47. }
  48.  
  49. /************************************************************************
  50. *                                    *
  51. * This method renders the scene using ray-tracing, at a resolution    *
  52. * specified by res. The method outputs an array of size            *
  53. * res[VX] * res[VY], each pixel being coded on 24 bits (8 bits per    *
  54. * color channel). The ray-tracing algorithm is simple and        *
  55. * non-recursive: it finds the closest intersection along each ray and    *
  56. * shades the corresponding point using Phong's reflection model.    *
  57. *                                    *
  58. ************************************************************************/
  59.  
  60. char* Scene3D::rayTrace(vec2 res)
  61. {
  62. int        i, j,
  63.         idx = 0;                // current image data
  64. char        *picture;                // storage for the ray-traced image
  65. vec3        ray_org(camera->position()),    // origin of the ray
  66.         ray_dir,                // direction of the ray
  67.         p,                    // point of intersection
  68.         n,                    // normal vector
  69.         l,                    // light vector
  70.         r,                    // reflection vector
  71.         I,                    // light intensity
  72.         p_color;                // color of the current pixel
  73. Primitive   *hit;                // object being intersected
  74. double        u,v,                // coordinates on the film plane
  75.         t, t_min,                // distance to the closest object
  76.         d;
  77.  
  78. // allocate enough room for a 24 bits picture
  79. picture = new char[(int)res[VX] * (int)res[VY] * 3];
  80.  
  81. // for each point in the picture
  82. for (v = 1.; v > -1.; v -= 2. / (res[VY] - 1.))
  83.     for (u = -1.; u < 1.; u += 2. / (res[VX] - 1.)) {
  84.     // compute the direction of the ray through that point
  85.     ray_dir = camera->pointToRay(vec2(u,v));
  86.  
  87.     // find the intersection with the closest primitive
  88.     t_min = FAR_AWAY;
  89.     for (i=0; i<primitiveN; i++)
  90.         if ((t = pList[i]->intersect(ray_org, ray_dir)) && t < t_min) {
  91.         t_min = t;
  92.         hit = pList[i];
  93.         }
  94.  
  95.     // shade the intersection point
  96.     if (t_min < FAR_AWAY) {
  97.         I = vec3(0.0);
  98.         p = ray_org + t_min * ray_dir;
  99.         n = hit->normalAt(p);
  100.  
  101.         // for all the light sources in the scene
  102.         for (j=0; j<lightN; j++) {
  103.  
  104.         // compute the light vector and the reflection vector
  105.         l = (lList[j]->position() - p).normalize();
  106.         r = 2.0 * (n * l) * n  - l;
  107.  
  108.         // add the diffuse component
  109.         if ((d = n * l) > 0.0)
  110.             I += hit->phong(KD) * d * lList[j]->color();
  111.  
  112.         // add the specular component
  113.         if ((d = -ray_dir * r) > 0.0)
  114.             I += hit->phong(KS) * pow(d, hit->phong(ES))
  115.             * lList[j]->color();
  116.         }
  117.         p_color = min(255.0 * prod(I, hit->color()), vec3(255.0));
  118.         }
  119.     else
  120.         p_color = vec3(0.0);
  121.     picture[idx++] = (int) p_color[RED];
  122.     picture[idx++] = (int) p_color[GREEN];
  123.     picture[idx++] = (int) p_color[BLUE];
  124.     }
  125. return picture;
  126. }
  127.  
  128. /************************************************************************
  129. *                                    *
  130. * This function converts vocabulary words specified in a vocabulary    *
  131. * table into integers equal to the index of the word in the table.    *
  132. * It automatically skips tabs, comment characters '%'.            *
  133. *                                    *
  134. ************************************************************************/
  135.  
  136. int parseStream(istream& s, char** vocabulary)
  137. {
  138. int    i;
  139. char    c,
  140.     string[1024];
  141.  
  142. // skip white space and comments
  143. while(s.get(c) && (isspace(c) || c == '%'))
  144.     if (c == '%')   // allow comment lines starting with the percent sign
  145.     while(s.get(c) && c != '\n') ;
  146. s.putback(c);
  147.  
  148. // read the text string and force it to uppercase
  149. strcpy(string, "");
  150. s >> string;
  151. for (i=0; i< strlen(string); i++)
  152.     string[i] = toupper(string[i]);
  153.  
  154. // If the string is in the dictionary, return its index
  155. i = 0;
  156. while(vocabulary[i]) {
  157.     if (strcmp(vocabulary[i], string) == 0)
  158.     break;
  159.     i++;
  160.     }
  161. return i+1;
  162. }
  163.  
  164. /************************************************************************
  165. *                                    *
  166. * Input from stream.                            *
  167. *                                    *
  168. ************************************************************************/
  169.  
  170. istream& operator >> (istream& s, Scene3D& a)
  171. {
  172. enum {CAMERA=1,
  173.       LIGHT=2,
  174.       SPHERE=3,
  175.       POLYHEDRON=4,
  176.       UNKNOWN=5};
  177. int        key;
  178. static char *key_words[] = {"CAMERA",
  179.                 "LIGHT",
  180.                 "SPHERE",
  181.                 "POLYHEDRON",
  182.                 0};
  183.  
  184. while ((key = parseStream(s, key_words)) && !s.eof())
  185.     switch(key) {
  186.     case CAMERA:
  187.         a.camera = new Camera;
  188.         s >> *a.camera;
  189.         break;
  190.  
  191.     case LIGHT:
  192.         Light *light = new Light;
  193.         a.lList[a.lightN++] = light;
  194.         s >> *light;
  195.         break;
  196.  
  197.     case SPHERE:
  198.         Sphere *sphere = new Sphere;
  199.         a.pList[a.primitiveN++] = sphere;
  200.         s >> *sphere;
  201.         break;
  202.  
  203.     case POLYHEDRON:
  204.         Polyhedron *polyhedron = new Polyhedron;
  205.         a.pList[a.primitiveN++] = polyhedron;
  206.         s >> *polyhedron;
  207.         break;
  208.  
  209.     case UNKNOWN:
  210.         cerr << "\nScene 3D: corrupted stream passed to operator >>";
  211.         return s;
  212.         break;
  213.     }
  214.  
  215. return s;
  216. }
  217.